﻿/************************************************************************

   Extended Silverlight Toolkit

   Copyright (C) 2010-2012 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license

   Please purchase a commercial version of this toolkit if you are using
   it in a commercial product. The commercial versions support the project,
   and also include more features for each control, priority support,
   source code, updates, removed watermark, and a proprietary license.

   Visit http://xceed.com and follow @datagrid on Twitter.

  **********************************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace Xceed.Silverlight.Data
{
  internal class SyncDebugLogDataSourceEnumerator : SyncDebugLogEnumerator<DataPath>, ISyncDataSourceEnumerator, IEnumerator<DataPath>
  {
    public SyncDebugLogDataSourceEnumerator( ISyncDataSourceEnumerator childEnumerator )
      : base( childEnumerator )
    {
      this.Initialize();
    }

    public SyncDebugLogDataSourceEnumerator( 
      ISyncDataSourceEnumerator childEnumerator, 
      Action<string> logger )
      : base( childEnumerator, logger )
    {
      this.Initialize();
    }

    private void Initialize()
    {
      ISyncDataSourceEnumerator dataSourceEnumerator = this.DataSourceEnumerator;

      dataSourceEnumerator.IndexChanged += new EventHandler<IndexChangedEventArgs>( DataSourceEnumerator_IndexChanged );
      dataSourceEnumerator.ItemCountChanged += new EventHandler( DataSourceEnumerator_ItemCountChanged );
      dataSourceEnumerator.HasPendingRequestsChanged += new EventHandler( DataSourceEnumerator_HasPendingRequestsChanged );
    }

    public long Index
    {
      get
      {
        //this.LogManager.LogBefore( "Index_get" );
        long ret = this.DataSourceEnumerator.Index;
        this.LogManager.LogSingle( "Index_get", ret );
        return ret;
      }
    }

    private ISyncDataSourceEnumerator DataSourceEnumerator
    {
      get
      {
        return ( ISyncDataSourceEnumerator )this.ChildEnumerator;
      }
    }

    protected override void Dispose( bool disposing )
    {
      if( disposing )
      {
        ISyncDataSourceEnumerator dataSourceEnumerator = this.DataSourceEnumerator;

        dataSourceEnumerator.IndexChanged -= new EventHandler<IndexChangedEventArgs>( DataSourceEnumerator_IndexChanged );
        dataSourceEnumerator.ItemCountChanged -= new EventHandler( DataSourceEnumerator_ItemCountChanged );
        dataSourceEnumerator.HasPendingRequestsChanged -= new EventHandler( DataSourceEnumerator_HasPendingRequestsChanged );
      }

      base.Dispose( disposing );
    }

    public bool MoveAndFetch( 
      bool approximateMove,
      long expectedMoveCount, 
      int expectedFetchCount,
      out Nullable<long> actualMoveCount, 
      out ICollection<DataPath> fetchedItems,
      out RelativeOffset endPositionOffset,
      out EstimateInt64 totalCount )
    {
      string moveParam = string.Format( "{0} ({1})", expectedMoveCount, approximateMove ? "approx" : "precise" );
      this.LogManager.LogBefore( "MoveAndFetch (typed)", "move=" + moveParam, "fetch=" + expectedFetchCount );
      bool ret = this.DataSourceEnumerator.MoveAndFetch(
                   approximateMove,
                   expectedMoveCount,
                   expectedFetchCount,
                   out actualMoveCount,
                   out fetchedItems,
                   out endPositionOffset,
                   out totalCount );

      moveParam = string.Format( "{0} ({1})", actualMoveCount, approximateMove ? "approx" : "precise" );
      this.LogManager.LogR( "MoveAndFetch (typed)", ret, "move=" + moveParam, FormatFetchedItems( DataUtils.ConvertToNonGeneric<DataPath>( fetchedItems ) ) );
      return ret;
    }

    public GroupFetchResult FetchGroup( DataPath groupPath, GroupTarget groupTarget, int expectedFetchCount )
    {
      this.LogManager.LogBefore( "FetchGroup", "group=" + groupPath, "groupTarget=" + groupTarget, "fetch=" + expectedFetchCount );
      GroupFetchResult ret = this.DataSourceEnumerator.FetchGroup( groupPath, groupTarget, expectedFetchCount );
      this.LogManager.LogR( "FetchGroup", ret.EndPositionObject.IsOutOfBound, FormatFetchedItems( DataUtils.ConvertToNonGeneric<DataPath>( ret.FetchedItems ) ) );
      return ret;
    }

    public bool IsFirst( DataPath path, int levelDepth )
    {
      this.LogManager.LogBefore( "IsLevelFirst", levelDepth, path  );
      bool ret = this.DataSourceEnumerator.IsFirst( path, levelDepth );
      this.LogManager.LogR( "IsLevelFirst", ret, levelDepth, path );
      return ret;
    }

    private void DataSourceEnumerator_ItemCountChanged( object sender, EventArgs e )
    {

      if( this.ItemCountChanged != null )
      {
        this.LogManager.LogBefore( "ItemCountChanged_event..." );
        this.ItemCountChanged( this, EventArgs.Empty );
        this.LogManager.LogAfter( "ItemCountChanged_event. Handled" );
      }
      else
      {
        this.LogManager.LogSingle( "ItemCountChanged_event. Not Handled" );
      }
    }

    private void DataSourceEnumerator_IndexChanged( object sender, IndexChangedEventArgs e )
    {
      if( this.IndexChanged != null )
      {
        this.LogManager.LogBefore( "IndexChanged_event..." );
        this.IndexChanged( this, e );
        this.LogManager.LogAfter( "IndexChanged_event. Handled" );
      }
      else
      {
        this.LogManager.LogSingle( "IndexChanged_event. Not Handled" );
      }
    }

    private void DataSourceEnumerator_HasPendingRequestsChanged( object sender, EventArgs e )
    {
      if( this.HasPendingRequestsChanged != null )
      {
        this.LogManager.LogBefore( "HasPendingRequestsChanged_event..." );
        this.HasPendingRequestsChanged( this, e );
        this.LogManager.LogAfter( "HasPendingRequestsChanged_event. Handled" );
      }
      else
      {
        this.LogManager.LogSingle( "HasPendingRequestsChanged_event. Not Handled" );
      }
    }

    #region IDataSourceEnumerator Members

    public long ItemCount
    {
      get
      {
        //this.LogManager.LogBefore( "ItemCount_get" );
        long ret = this.DataSourceEnumerator.ItemCount;
        this.LogManager.LogSingle( "ItemCount_get", ret );
        return ret;
      }
    }

    public event EventHandler<IndexChangedEventArgs> IndexChanged;
    public event EventHandler ItemCountChanged;

    #endregion

    #region IPendingRequests Members

    public bool HasPendingRequests
    {
      get
      {
        return this.DataSourceEnumerator.HasPendingRequests;
      }
    }

    public event EventHandler HasPendingRequestsChanged;

    #endregion

    #region IEnumerator<DataPath> Members

    public virtual DataPath Current
    {
      get
      {
        this.LogManager.LogBefore( "Current_get" );
        DataPath ret = this.DataSourceEnumerator.Current;
        this.LogManager.LogR( "Current_get", ret );
        return ret;
      }
    }

    #endregion IEnumerator<DataPath> Members

    #region IEnumerator Members

    object IEnumerator.Current
    {
      get
      {
        this.LogManager.LogBefore( "Current_get (untyped)" );
        object ret = this.DataSourceEnumerator.Current;
        this.LogManager.LogR( "Current_get (untyped)", ret );
        return ret;
      }
    }

    public virtual bool MoveNext()
    {
      this.LogManager.LogBefore( "MoveNext" );
      bool ret = this.DataSourceEnumerator.MoveNext();
      this.LogManager.LogR( "MoveNext", ret );
      return ret;
    }

    public virtual void Reset()
    {
      this.LogManager.LogBefore( "Reset" );
      this.DataSourceEnumerator.Reset();
      this.LogManager.LogAfter( "Reset" );
    }

    #endregion IEnumerator Members
  }
}
